我有分寸

[译文] NOSQL们背后的共有原则

gnawux cloudnosqltranslation

原文: http://natishalom.typepad.com/nati_shaloms_blog/2009/12/the-common-principles-behind-the-nosql-alternatives.html
Posted by Nati Shalom at 12:01 PM Dec 15, 2009
译文: 王旭(http://wangxu.me , @gnawux)2009年12月16/19日

几个星期之前,我写了一篇文章描述了常被称作 NOSQL 的一类新型数据库的背后驱动。几个星期之前,我在Qcon上发表了一个演讲,其中,我介绍了一个可伸缩(scalable)的 twitter 应用的构建模式,在我们的讨论中,一个显而易见的问题就是数据库的可扩展性问题。要解答这个问题,我试图寻找隐藏在各种 NOSQL 之后的共有模式,并展示他们是如何解决数据库可扩展性问题的。在本文中,我将尽力勾勒出这些共有的原则。

nosql

实现们的共有原则

假设失效是必然发生的

与我们先前通过昂贵硬件之类的手段尽力去避免失效的手段不同,NOSQL实现都建立在硬盘、机器和网络都会失效这些假设之上。我们需要认定,我们不能彻底阻止这些时效,相反,我们需要让我们的系统能够在即使非常极端的条件下也能应付这些失效。Amazon S3 就是这种设计的一个好例子。你可以在我最近的文章 Why Existing Databases (RAC) are So Breakable! 中找到进一步描述。哪里,我介绍了一些来自 Jason McHugh 的讲演的面向失效的架构设计的内容(Jason 是在 Amazon 做 S3 相关工作的高级工程师)。

对数据进行分区

通过对数据进行分区,我们最小化了失效带来的影响,也将读写操作的负载分布到了不同的机器上。如果一个节点失效了,只有该节点上存储的数据受到影响,而不是全部数据。

保存同一数据的多个副本

大部分 NOSQL 实现都基于数据副本的热备份来保证连续的高可用性。一些实现提供了 API,可以控制副本的复制,也就是说,当你存储一个对象的时候,你可以在对象级指定你希望保存的副本数。在 GigaSpaces,我们还可以立即复制一个新的副本到其他节点,甚至在必要时启动一台新机器。这让我们不比在每个节点上保存太多的数据副本,从而降低总存储量以节约成本。

你还可以控制副本复制是同步还是异步的,或者两者兼有。这决定了你的集群的一致性、可用性与性能三者。对于同步复制,可以牺牲性能保障一致性和可用性(写操作之后的任意读操作都可以保证得到相同版本的数据,即使是发生失效也会如此)。而最为常见的 GigaSpaces 的配置是同步副本到被分界点,异步存储到后端存储。

动态伸缩

要掌控不断增长的数据,大部分 NOSQL 实现提供了不停机或完全重新分区的扩展集群的方法。一个已知的处理这个问题的算法称为一致哈希。有很多种不同算法可以实现一致哈希。

一个算法会在节点加入或失效时通知某一分区的邻居。仅有这些节点受到这一变化的影响,而不是整个集群。有一个协议用于掌控需要在原有集群和新节点之间重新分布的数据的变换区间。

另一个(简单很多)的算法使用逻辑分区。在逻辑分区中,分区的数量是固定的,但分区在机器上的分布式动态的。于是,例如有两台机器和1000个逻辑分区,那么每500个逻辑分区会放在一台机器上。当我们加入了第三台机器的时候,就成了每 333 个分区放在一台机器上了。因为逻辑分区是轻量级的(基于内存中的哈希表),分布这些逻辑分区非常容易。

第二种方法的优势在于它是可预测并且一致的,而使用一致哈希方法,分区之间的重新分布可能并不平稳,当一个新节点加入网络时可能会消耗更长时间。一个用户在这时寻找正在转移的数据会得到一个异常。逻辑分区方法的缺点是可伸缩性受限于逻辑分区的数量。

更进一步的关于这一问题的讨论,建议阅读 Ricky Ho 的文章 NOSQL Patterns

查询支持

在这个方面,不同的实现有相当本质的区别。不同实现的一个共性在于哈希表中的 key/value 匹配。一些市县提供了更高级的查询支持,比如面向文档的方法,其中数据以 blob 的方式存储,关联一个键值对属性列表。这种模型是一种无预定义结构的(schema-less)存储,给一个文档增加或删除属性非常容易,无需考虑文档结构的演进。而 GigaSpaces 支持很多 SQL 操作。如果 SQL查询没有指出特定的简直,那么这个查询就会被并行地 map 到所有的节点去,由客户端完成结果的汇聚。所有这些都是发生在幕后的,用户代码无需关注这些。

使用 Map/Reduce 处理汇聚

Map/Reduce 是一个经常被用来进行复杂分析的模型,经常会和 Hadoop 联系在一起。 map/reduce 常常被看作是并行汇聚查询的一个模式。大部分 NOSQL 实现并不提供 map/reduce 的内建支持,需要一个外部的框架来处理这些查询。对于 GigaSpaces 来说,我们在 SQL 查询中隐含了对 map/reduce 的支持,同时也显式地提供了一个称为 executors 的 API 来支持 map/reduce。在质疑模型中,你可以将代码发送到数据所在地地方,并在该节点上直接运行复杂的查询。

这方面的更多细节,建议阅读 Ricky Ho 的文章 Query Processing for NOSQL DB

基于磁盘的和内存中的实现

NOSQL 实现分为基于文件的方法和内存中的方法。有些实现提供了混合模型,将内存和磁盘结合使用。两类方法的最主要区别在于每 GB 成本和读写性能。

最近,斯坦福的一项称为“The Case for RAMCloud”的调查,对磁盘和内存两种方法给出了一些性能和成本方面的有趣的比较。总体上说,成本也是性能的一个函数。对于较低性能的实现,磁盘方案的成本远低于基于内存的方法,而对于高性能需求的场合,内存方案则更加廉价。

内存云的显而易见的缺点就是单位容量的高成本和高能耗。对于这些指标,内存云会比纯粹的磁盘系统差50到100倍,比使用闪存的系统差5-10倍(典型配置情况和指标参见参考文献[1])。内存云同时还比基于磁盘和闪存的系统需要更多的机房面积。这样,如果一个应用需要存储大量的廉价数据,不需要高速访问,那么,内存云将不是最佳选择。
然而,对于高吞吐量需求的应用,内存云将更有竞争力。当使用每次操作的成本和能量作为衡量因素的时候,内存云的效率是传统硬盘系统的 100 到 1000 倍,是闪存系统的 5-10 倍。因此,对于高吞吐量需求的系统来说,内存云不仅提供了高性能,也提供了高能源效率。同时,如果使用 DRAM 芯片提供的低功耗模式,也可以降低内存云的功耗,特别是在系统空闲的时候。此外,内存云还有一些缺点,一些内存云无法支持需要将数据在多个数据中心之间进行数据复制。对于这些环境,更新的时延将主要取决于数据中心间数据传输的时间消耗,这就丧失了内存云的时延方面的优势。此外,跨数据中心的数据复制会让内存云数据一致性更能难保证。不过,内存云仍然可以在夸数据中心的情况下提供低时延的读访问。

仅仅是炒作?

近来我见到的最多的问题就是 “NOSQL 是不是就是炒作?” 或 “NOSQL 会不会取代现在的数据库?”

我的回答是——NOSQL 并非始于今日。很多 NOSQL 实现都已经存在了十多年了,有很多成功案例。我相信有很多原因让它们在如今比以往更受欢迎了。首先是由于社会化网络和云计算的发展,一些原先只有很高端的组织才会面临的问题,如今已经成为普遍问题了。其次,已有的方法已经被发现无法跟随需求一起扩展了。并且,成本的压力让很多组织需要去寻找更高性价比的方案,并且研究证实基于普通廉价硬件的分布式存储解决方案甚至比现在的高端数据库更加可靠。(进一步阅读)所有这些导致了对这类“可伸缩性优先数据库”的需求。这里,我引用 AWS团队的接触工程师、VP, James Hamilton 在他的文章 One Size Does Not Fit All 中的一段话:

“伸缩性优先应用是那些必须具备无限可伸缩性的应用,能够不受限制的扩展比更丰富的功能更加重要。这些应用包括很多需要高可伸缩性的网站,如 Facebook, MySpace, Gmail, Yahoo 以及 Amazon.com。有些站点实际上使用了关系型数据库,而大部分实际上并未使用。这些服务的共性在于可扩展性比功能公众要,他们无法泡在一个单一的 RDBMS 上。”

总结一下——我认为,现有的 SQL 数据库可能不会很快淡出历史舞台,但同时它们也不能解决世上的所有问题。NOSQL 这个名词现在也变成了 Not Only SQL,这个变化表达了我的观点。

参考:

gnawux
me!#$!@#$@#$wangxu!@#$%^&*()_me